/*
 * Copyright 2008. Mount Sinai Hospital, Toronto, Canada.
 * 
 * Licensed under the Apache License, Version 2.0. You
 * can find a copy of the license at:
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * IN NO EVENT SHALL MOUNT SINAI HOSPITAL BE LIABLE TO ANY PARTY FOR DIRECT, 
 * INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST 
 * PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, 
 * EVEN IF MOUNT SINAI HOSPITAL HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 
 * DAMAGE.
 * 
 * MOUNT SINAI HOSPITAL SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF 
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE AND 
 * ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". 
 * MOUNT SINAI HOSPITAL HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, 
 * UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 
 */

package com.sinai.mshab.format;

import java.util.ArrayList;

import com.google.gwt.user.client.ui.Widget;

/**
 * This class manages all visibility logic, when things should be hidden or
 * shown.
 * 
 * @author serge
 * 
 */
public class VisibilityManager {

	// we need to remember all our rules.
	private ArrayList<VisiblityRule> rules = new ArrayList<VisiblityRule>();

	private static VisibilityManager visibility;

	private VisibilityManager() {

	}

	/**
	 * Returns an instance of the visibility manager
	 * 
	 * @return an instance of the visibility manager
	 */
	public static VisibilityManager getInstance() {
		if (visibility == null) {
			visibility = new VisibilityManager();
		}
		return visibility;
	}

	/**
	 * Adds a new rule, original widget will be shown if conditional widget is
	 * set.
	 * 
	 * @param original
	 *            the widget to hide or show
	 * @param conditional
	 *            the widget on whos value we decide to hide or show original
	 */
	public void addShowRule(Widget original, Widget conditional) {
		VisiblityRule rule = new VisiblityRule(original, conditional,
				VisiblityRule.SHOW);
		rules.add(rule);
		rule.execute();
	}

	/**
	 * Adds a new rule, original widget will be hidden if conditional widget is
	 * set.
	 * 
	 * @param original
	 *            the widget to hide or show
	 * @param conditional
	 *            the widget on whos value we decide to hide or show original
	 */
	public void addHideRule(FormattingContainer original, Widget conditional) {
		VisiblityRule rule = new VisiblityRule(original, conditional,
				VisiblityRule.HIDE);
		rules.add(rule);
		rule.execute();
	}

	/**
	 * Adds a show/hide rule, the original widget will only be shown if the
	 * value of the conditional widget matches some regex
	 * 
	 * @param original the widget to hide or show
	 * @param conditional the trigger widget
	 * @param regex the regex that must be met for the widget to show
	 */
	public void addValueRule(FormattingContainer original, Widget conditional,
			String regex) {
		VisiblityRule rule = new VisiblityRule(original, conditional, regex);
		rules.add(rule);
		rule.execute();
	}

	/**
	 * Executes all known visibility rules. Calling this method is useful after
	 * something like populate() due to the fact that there is no user
	 * interaction during the process, thus no onChange events are fired off to
	 * trigger rules.
	 */
	public void applyAllRules() {
		for (int i = 0; i < rules.size(); i++) {
			VisiblityRule rule = rules.get(i);
			rule.execute();
		}
	}
}
